package com.superhelper.processor.order.consumer;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import com.aliyun.openservices.ons.api.Action;
import com.aliyun.openservices.ons.api.ConsumeContext;
import com.aliyun.openservices.ons.api.Message;
import com.aliyun.openservices.ons.api.MessageListener;
import com.aliyun.openservices.ons.api.ONSFactory;
import com.aliyun.openservices.ons.api.PropertyKeyConst;
import com.superhelper.common.Consts;
import com.superhelper.common.domain.AuserShop;
import com.superhelper.common.domain.POIStatus;
import com.superhelper.common.domain.POIStatusOperator;
import com.superhelper.common.domain.PushMsgType;
import com.superhelper.common.domain.TakeOutOrder;
import com.superhelper.common.domain.TakeOutOrderBackup;
import com.superhelper.common.domain.TakeOutOrderGroup;
import com.superhelper.common.domain.TakeOutOrderGroupItem;
import com.superhelper.common.domain.TakeOutOrderGroupType;
import com.superhelper.common.domain.TakeOutOrderStatus;
import com.superhelper.common.domain.TakeOutOrderType;
import com.superhelper.common.domain.User;
import com.superhelper.common.domain.baidu.BdPushEntity;
import com.superhelper.common.exception.ServiceException;
import com.superhelper.common.service.BaiduService;
import com.superhelper.common.utils.CoodinateCovertor;
import com.superhelper.common.utils.CoodinateCovertor.Coordinate;
import com.superhelper.common.utils.GeoUtil;
import com.superhelper.common.utils.JsonHelper;
import com.superhelper.common.utils.JsonObjectUtil;

@Component
public class BdOrderConsumer extends AbstractOrderConsumer implements ApplicationListener<ContextRefreshedEvent> {

    @Value("${aliyun.access.key}")
    private String aliyunAccessKey;
    @Value("${aliyun.access.secret}")
    private String aliyunSecretKey;

    @Value("${aliyun.bd.order.consumer.id}")
    private String consumerId;
    @Value("${order.topic}")
    private String orderTopic;
    @Value("${online}")
    private boolean online;

    @Autowired
    private BaiduService baiduService;
    // @Autowired
    // private HttpClientHelper httpClient;
    private static String[] CN_SEQ = new String[] { "一", "二", "三", "四", "五", "六", "七", "八", "九", "十" };

    public static String getChinaSeq(int num) {
        if (num <= 0) {
            return "零";
        }
        int index = num - 1;
        if (index <= 9) {
            return CN_SEQ[index];
        }
        int cs = num / 10;
        String res = (cs == 1 ? "" : CN_SEQ[cs - 1]) + "十";
        int mod = num % 10 - 1;
        if (mod < 0) {
            return res;
        }
        return res + CN_SEQ[mod];
    }

    @Override
    public void onApplicationEvent(ContextRefreshedEvent event) {
        if (event.getApplicationContext().getParent() != null) {
            return;
        }
        if (consumer != null) {
            return;
        }
        init();
        String tag = orderTopic + online + "-bd";
        consumer.subscribe(orderTopic, tag, new MessageListener() {
            public Action consume(Message message, ConsumeContext context) {
                try {
                    String content = new String(message.getBody(), Consts.UTF8_CHARSET);
                    log.info("content is:{}", content);
                    BdPushEntity entity = JsonHelper.fromJson(content, BdPushEntity.class);
                    if (entity == null) {
                        log.error("BdOrderConsumer entity is null");
                        return Action.CommitMessage;
                    }
                    PushMsgType type = PushMsgType.getByBdType(entity.getCmd(), entity.getBody());
                    if (type == null || type == PushMsgType.UNKNOWN) {
                        log.error("BdOrderConsumer ingore,because no pushMsgType:{}", entity.getBody());
                        return Action.CommitMessage;
                    }
                    String orderId = (String) entity.getBody().get("order_id");
                    entity.getBody().put("orderId", orderId);
                    // 下单消息
                    if (type == PushMsgType.ORDER_CREATED) {
                        createOrder(entity);
                    } else if (type == PushMsgType.ORDER_ACCEPTED) {
                        dealOrder(TakeOutOrderStatus.VALID.getValue(), JsonHelper.toJson(entity.getBody()), type,
                                TakeOutOrderType.BaiDu.getValue());
                    } else if (type == PushMsgType.ORDER_COMPLETED) {
                        dealOrder(TakeOutOrderStatus.SETTLED.getValue(), JsonHelper.toJson(entity.getBody()), type,
                                TakeOutOrderType.BaiDu.getValue());
                    } else if (type == PushMsgType.ORDER_CANCELED) {
                        dealOrder(TakeOutOrderStatus.INVALID.getValue(), JsonHelper.toJson(entity.getBody()), type,
                                TakeOutOrderType.BaiDu.getValue());
                    } else if (type == PushMsgType.ORDER_REFUND) {
                        dealOrder(TakeOutOrderStatus.REFUNDING.getValue(), JsonHelper.toJson(entity.getBody()), type,
                                TakeOutOrderType.BaiDu.getValue());
                    } else if (type == PushMsgType.ORDER_APPLY_CANCEL) {
                        dealOrder(TakeOutOrderStatus.APPLY_CANCEL.getValue(), JsonHelper.toJson(entity.getBody()),
                                type, TakeOutOrderType.BaiDu.getValue());
                    } else if (type == PushMsgType.ORDER_REVOKE_CANCEL) {
                        dealOrder(TakeOutOrderStatus.VALID.getValue(), JsonHelper.toJson(entity.getBody()), type,
                                TakeOutOrderType.BaiDu.getValue());
                    } else if (type == PushMsgType.ORDER_AGREE_CANCEL) {
                        dealOrder(TakeOutOrderStatus.INVALID.getValue(), JsonHelper.toJson(entity.getBody()), type,
                                TakeOutOrderType.BaiDu.getValue());
                    } else if (type == PushMsgType.ORDER_REJECT_CANCEL) {
                        dealOrder(TakeOutOrderStatus.VALID.getValue(), JsonHelper.toJson(entity.getBody()), type,
                                TakeOutOrderType.BaiDu.getValue());
                    } else if (type == PushMsgType.DELIVER_STATUS) {
                        dealOrder(TakeOutOrderStatus.DELIVERING.getValue(), JsonHelper.toJson(entity.getBody()), type,
                                TakeOutOrderType.BaiDu.getValue());
                    } else if (type == PushMsgType.POI_STATUS) {
                        dealPoiStatus(entity);
                    }

                } catch (Exception e) {
                    log.error("BdOrderConsumer error", e);
                    return Action.ReconsumeLater;
                }
                return Action.CommitMessage;
            }
        });
        consumer.start();
        log.info("consumer started");
    }

    private void dealPoiStatus(BdPushEntity entity) {
        Map<String, Object> body = entity.getBody();
        if (body == null) {
            return;
        }
        // "shop_id": "123233",
        // "status": "9",
        // "change_time": 1473167295,
        // "descrption": "暂停营业",
        // "reason": "【原因】其他【备注】sdfds",
        // "user": "【百度】dengfeng"
        String partnerId = MapUtils.getString(body, "shop_id");
        String reason = MapUtils.getString(body, "reason");
        String status = MapUtils.getString(body, "status");
        String user = MapUtils.getString(body, "user");
        AuserShop shop = orderMapper.getShopByPartnerId(partnerId, TakeOutOrderType.BaiDu.getValue());
        publishShopStatus(shop.getShopId(), TakeOutOrderType.BaiDu, POIStatus.bd(status), POIStatusOperator.bd(user),
                reason);
    }

    private String getOrderDetail(String source, String orderId) {
        return baiduService.getOrder(source, orderId);
    }

    private void createOrder(BdPushEntity entity) throws ServiceException {

        String orderId = (String) entity.getBody().get("order_id");

        String resp = getOrderDetail(entity.getSource(), orderId);
        if (resp == null) {
            throw new ServiceException(Consts.Code.NET_CONN_ERROR, "获取订单详情失败 ");
        }
        entity = JsonHelper.fromJson(resp, BdPushEntity.class);

        @SuppressWarnings("unchecked")
        Map<String, Object> dataMap = (Map<String, Object>) entity.getBody().get("data");
        if (dataMap == null) {
            return;
        }

        TakeOutOrder order = new TakeOutOrder();
        convert(order, dataMap);

        String phone = CollectionUtils.isEmpty(order.getPhoneList()) ? order.getPhone() : order.getPhoneList().get(0);
        User user = null;
        if (StringUtils.isNotBlank(phone)) {
            AuserShop shop = orderMapper.getShop(order.getShopId(), order.getType());
            user = userMapper.getUser(phone, shop.getAuserId());
            if (user == null) {
                user = new User();
                user.setSource(TakeOutOrderType.BaiDu.getValue());
                user.setPhone(phone);
                user.setCreateAt(new Date());
                user.setName(order.getConsigness());
                user.setEle_money(BigDecimal.valueOf(order.getTotalPrice()));
                user.setIntegral(BigDecimal.valueOf(order.getTotalPrice()).intValue());
                user.setMt_money(BigDecimal.ZERO);
                user.setAuserId(shop.getAuserId());
                userMapper.insertUser(user);
            }
        }
        order.setUserId(user != null ? user.getId() : 0l);

        TakeOutOrder too = orderMapper.getByPlfOrderIdAndType(order.getPlfOrderId(), order.getType());
        if (too != null) {
            log.info("BdOrderConsumer entity,reqId:{} is duplicate msg");
        } else {

            orderMapper.insertOrder(order);
            List<TakeOutOrderGroup> groups = order.getGroups();
            if (groups != null) {
                for (TakeOutOrderGroup group : groups) {
                    group.setOrderId(order.getId());
                    orderMapper.insertGroup(group);
                    List<TakeOutOrderGroupItem> items = group.getItems();
                    if (items != null) {
                        for (TakeOutOrderGroupItem item : items) {
                            item.setGroupId(group.getId());
                            item.setOrderId(group.getOrderId());
                            orderMapper.insertGroupItem(item);
                        }
                    }
                }
            }
            TakeOutOrderBackup orderBackup = new TakeOutOrderBackup();
            orderBackup.setOrderId(order.getId());
            orderBackup.setContent(JsonHelper.toJson(entity));
            orderMapper.insertOrderBackup(orderBackup);
            publish(order, PushMsgType.ORDER_CREATED, false);
        }
    }

    @SuppressWarnings("unchecked")
    private void convert(TakeOutOrder order, Map<String, Object> dataMap) {
        Map<String, Object> orderMap = (Map<String, Object>) dataMap.get("order");
        Map<String, Object> userMap = (Map<String, Object>) dataMap.get("user");
        Map<String, Object> shopMap = (Map<String, Object>) dataMap.get("shop");

        order.setType(TakeOutOrderType.BaiDu.getValue());
        order.setPlfOrderId(MapUtils.getString(orderMap, "order_id"));
        order.setPlfOrderCode(order.getPlfOrderId());
        order.setPlfCreateAt(new Date(1000 * NumberUtils.toLong(MapUtils.getString(orderMap, "create_time"))));
        order.setActiveAt(order.getPlfCreateAt());
        order.setCreateAt(new Date());
        order.setDeliverFee(0d);
        order.setThirdDeliver("2".equals(MapUtils.getString(orderMap, "delivery_party")));
        long deliverTime = NumberUtils.toLong(MapUtils.getString(orderMap, "send_time"));
        if (deliverTime > 1) {
            order.setDeliverTime(new Date(1000 * deliverTime));
            order.setBook(true);
        } else {
            order.setBook(false);
        }
        order.setDescription(MapUtils.getString(orderMap, "remark"));
        order.setInvoice(MapUtils.getString(orderMap, "invoice_title"));
        order.setInvoiced("1".equals(MapUtils.getString(orderMap, "need_invoice")));

        order.setPayType("2".equals(MapUtils.getString(orderMap, "pay_type")) ? TakeOutOrder.PAY_TYPE_PAID
                : TakeOutOrder.PAY_TYPE_NOTPAID);

        order.setPhone(MapUtils.getString(userMap, "phone"));
        order.setShopId(MapUtils.getString(shopMap, "baidu_shop_id"));
        order.setShopName(MapUtils.getString(shopMap, "name"));

        order.setDaySn(MapUtils.getInteger(orderMap, "order_index"));

        // 推单方式，没有订单信息
        order.setStatus(TakeOutOrderStatus.getByBdStatus(MapUtils.getInteger(orderMap, "status")).getValue());
        order.setStatusMsg("创建订单");
        order.setRefundStatus("noRefund");
        order.setTotalPrice(JsonObjectUtil.getInt(orderMap.get("user_fee")) / 100.0);
        order.setOriPrice(JsonObjectUtil.getInt(orderMap.get("total_fee")) / 100.0);
        order.setConsigness(MapUtils.getString(userMap, "name"));
        Map<String, Object> geo = (Map<String, Object>) userMap.get("coord");

        if (geo != null && geo.size() >= 2) {

            order.setDeliverLon(NumberUtils.toDouble("" + geo.get("longitude")));
            order.setDeliverLat(NumberUtils.toDouble("" + geo.get("latitude")));

            Coordinate c = CoodinateCovertor.fromBd(new CoodinateCovertor.Coordinate(order.getDeliverLon(), order
                    .getDeliverLat()));

            order.setDeliverLon(c.getLongitude());
            order.setDeliverLat(c.getLantitude());

            AuserShop s = orderMapper.getShop(order.getShopId(), order.getType());
            if (s != null) {
                order.setAuserId(s.getAuserId().longValue());
                order.setDist(GeoUtil.calDist(order.getDeliverLon(), order.getDeliverLat(), s.getLon(), s.getLat()));
            }
        }
        order.setDeliverPoi(MapUtils.getString(userMap, "district") + MapUtils.getString(userMap, "address"));

        order.setIncome(JsonObjectUtil.getInt(orderMap.get("shop_fee")) / 100.0);
        order.setHongbao(0d);
        order.setServiceRate(0d);
        order.setActivityTotal(0d);
        order.setServiceFee(JsonObjectUtil.getInt(orderMap.get("commission")) / 100.0);
        order.setPackageFee(JsonObjectUtil.getInt(orderMap.get("package_fee")) / 100.0);
        order.setDeliverFee(JsonObjectUtil.getInt(orderMap.get("send_fee")) / 100.0);

        List<Map<String, Object>> discountList = (List<Map<String, Object>>) dataMap.get("discount");
        double shopPart = 0d;
        double plfPart = 0d;
        if (!CollectionUtils.isEmpty(discountList)) {

            for (Map<String, Object> disMap : discountList) {
                double fee = JsonObjectUtil.getInt(disMap.get("fee")) / 100.0;
                double shopRate = JsonObjectUtil.getInt(disMap.get("shop_rate")) / 100.0;
                shopPart += shopRate;
                plfPart += (fee - shopRate);
            }
        }
        order.setShopPart(shopPart);
        order.setPlfPart(plfPart);
        // build Groups
        List<List<Map<String, Object>>> groupList = (List<List<Map<String, Object>>>) dataMap.get("products");
        if (!CollectionUtils.isEmpty(groupList)) {
            double boxFeeTotal = 0d;
            List<TakeOutOrderGroup> groups = new ArrayList<>();
            order.setGroups(groups);
            int index = 0;
            for (List<Map<String, Object>> gmList : groupList) {
                TakeOutOrderGroup group = new TakeOutOrderGroup();
                group.setName(getChinaSeq(++index) + "号袋");
                group.setType(TakeOutOrderGroupType.Normal.getValue());
                groups.add(group);
                List<TakeOutOrderGroupItem> items = new ArrayList<>();
                group.setItems(items);
                for (Map<String, Object> itemMap : gmList) {
                    TakeOutOrderGroupItem item = new TakeOutOrderGroupItem();
                    items.add(item);
                    item.setQuantity(NumberUtils.toInt(MapUtils.getString(itemMap, "product_amount")));
                    item.setBarCode(null);
                    item.setExtendCode((String) itemMap.get("product_custom_index"));
                    item.setTotal(JsonObjectUtil.getInt(itemMap.get("product_fee")) / 100.0);
                    item.setPrice(JsonObjectUtil.getInt(itemMap.get("product_price")) / 100.0);
                    item.setSkuId(MapUtils.getString(itemMap, "baidu_product_id"));
                    item.setName((String) itemMap.get("product_name"));
                    item.setCategoryId("" + itemMap.get("product_type"));

                    // item.setAdditions(ReflectionToStringBuilder.toString(itemMap.get("product_attr")));
                    try {
                        List<Map<String, String>> attrs = (List<Map<String, String>>) itemMap.get("product_features");
                        if (!CollectionUtils.isEmpty(attrs)) {
                            List<String> attrList = new ArrayList<>();
                            for (Map<String, String> m : attrs) {
                                attrList.add(m.get("option"));
                            }
                            item.setAttributes(StringUtils.join(attrList, "+"));
                        }

                        // item.setAttributes(JsonHelper.toJson(itemMap.get("product_attr")));

                        List<Map<String, String>> specs = (List<Map<String, String>>) itemMap.get("product_attr");
                        if (!CollectionUtils.isEmpty(specs)) {
                            List<String> specsList = new ArrayList<>();
                            for (Map<String, String> m : specs) {
                                specsList.add(m.get("option"));
                            }
                            item.setNewSpecs(StringUtils.join(specsList, "+"));
                        }
                    } catch (Exception e) {
                        log.error("attr error", e);
                    }
                    // item.setNewSpecs(JsonHelper.toJson(itemMap.get("product_features")));
                    // item.setWeight(JsonObjectUtil.getDouble(itemMap.get("weight")));
                    boxFeeTotal += JsonObjectUtil.getInt(itemMap.get("package_fee")) / 100.0;
                }
            }

            TakeOutOrderGroup g = new TakeOutOrderGroup();
            g.setType(TakeOutOrderGroupType.Extra.getValue());
            g.setName("其他费用");
            g.setItems(new ArrayList<TakeOutOrderGroupItem>());
            groups.add(g);
            TakeOutOrderGroupItem gi = new TakeOutOrderGroupItem();
            gi.setPrice(boxFeeTotal);
            gi.setQuantity(1);
            gi.setTotal(boxFeeTotal);
            gi.setName("餐盒");
            gi.setSkuId("-1");
            gi.setWeight(0d);
            g.getItems().add(gi);
        }
    }

    private void init() {
        Properties properties = new Properties();
        properties.put(PropertyKeyConst.ConsumerId, consumerId);
        properties.put(PropertyKeyConst.AccessKey, aliyunAccessKey);
        properties.put(PropertyKeyConst.SecretKey, aliyunSecretKey);
        consumer = ONSFactory.createConsumer(properties);
    }

    public static void main(String[] args) {
        String str = "{\"cmd\":\"resp.order.get\",\"version\":\"3\",\"sign\":\"1631C34D60CB0F384A5D20DC1F6B5521\",\"encrypt\":\"\",\"timestamp\":1504757105,\"ticket\":\"8C0A80D3-7EF2-B87A-6C2B-154EC6DB9101\",\"body\":{\"errno\":0,\"error\":\"success\",\"data\":{\"source\":\"31198\",\"shop\":{\"id\":\"1655383069\",\"name\":\"陈记土耳其烤肉（珠影分店）\",\"baidu_shop_id\":\"1655383069\"},\"order\":{\"expect_time_mode\":1,\"pickup_time\":0,\"atshop_time\":0,\"delivery_time\":0,\"delivery_phone\":\"\",\"finished_time\":\"0\",\"confirm_time\":\"0\",\"meal_num\":\"\",\"commission\":143,\"order_id\":\"15047570665604\",\"order_index\":\"2\",\"status\":1,\"send_immediately\":1,\"send_time\":\"1\",\"send_fee\":590,\"package_fee\":100,\"discount_fee\":1700,\"total_fee\":4380,\"shop_fee\":2837,\"user_fee\":2680,\"responsible_party\":\"\",\"pay_type\":2,\"pay_status\":2,\"need_invoice\":2,\"invoice_title\":\"\",\"taxer_id\":\"\",\"remark\":\"\",\"delivery_party\":2,\"create_time\":\"1504757066\",\"cancel_time\":\"0\"},\"user\":{\"name\":\"陈仕廷\",\"phone\":\"17620045001\",\"gender\":1,\"address\":\"逸景翠园-东区 荔影居c-1103\",\"province\":\"广东省\",\"city\":\"广州市\",\"district\":\"海珠区\",\"coord\":{\"longitude\":113.315911,\"latitude\":23.08984}},\"products\":[[{\"baidu_product_id\":\"1735200232\",\"upc\":\"\",\"product_name\":\"二号烤肉卷+任意烤肉饭+饮料_黑椒烤肉饭\",\"product_type\":1,\"product_price\":3690,\"product_amount\":1,\"product_fee\":3690,\"package_price\":100,\"package_amount\":\"1\",\"package_fee\":100,\"total_fee\":3790,\"product_attr\":[{\"baidu_attr_id\":\"2100290324\",\"attr_id\":\"2100290324\",\"name\":\"规格\",\"option\":\"黑椒烤肉饭\"}],\"product_features\":[{\"baidu_feature_id\":\"2100290319\",\"name\":\"饮料\",\"option\":\"雪碧\"}],\"product_custom_index\":\"1735200232_2100290319_31738286\",\"product_subsidy\":{\"discount\":1655,\"baidu_rate\":292,\"shop_rate\":1363,\"agent_rate\":0,\"logistics_rate\":0}}]],\"discount\":[{\"type\":\"jian\",\"activity_id\":\"1025495\",\"rule_id\":\"1179720\",\"fee\":1400,\"baidu_rate\":0,\"shop_rate\":1400,\"agent_rate\":0,\"logistics_rate\":0,\"desc\":\"立减优惠\"},{\"type\":\"coupon\",\"activity_id\":\"201132376704\",\"rule_id\":\"201132376704\",\"fee\":300,\"baidu_rate\":300,\"shop_rate\":0,\"agent_rate\":0,\"logistics_rate\":0,\"desc\":\"老用户餐饮代金券\"}],\"part_refund_info\":[]}},\"source\":\"31198\"}";
        BdPushEntity orderDetail = JsonHelper.fromJson(str, BdPushEntity.class);
        TakeOutOrder order = new TakeOutOrder();
        Map<String, Object> dataMap = (Map<String, Object>) orderDetail.getBody().get("data");
        new BdOrderConsumer().convert(order, dataMap);
        System.out.println(JsonHelper.toJson(order));

    }
}
